package com.study.controller;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

@RestController
public class ScheduleController {

    private final static Map<String, Task> taskMap = new HashMap<String, Task>();

    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {

        ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
        executor.setPoolSize(20);
        executor.setThreadNamePrefix("mytaskExecutor-");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        return executor;
    }

    /**
     * 创建定时任务
     *
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/startTask/{id}")
    public String start(@PathVariable("id") String id) throws InterruptedException {
        if (!StringUtils.isEmpty(id) && !taskMap.containsKey(id)) {
            Task task = new Task(id);
            ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(task.getRunnable(), new Trigger() {
                @Override
                public Date nextExecutionTime(TriggerContext triggerContext) {
                    return new CronTrigger(task.getCron()).nextExecutionTime(triggerContext);
                }
            });

            task.setScheduledFuture(future);
            taskMap.put(id, task);
        }
        return "success";
    }

    /**
     * 删除定时任务
     *
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/deleteTask/{id}")
    public String delete(@PathVariable("id") String id) throws InterruptedException {
        if (taskMap.containsKey(id)) {
            System.out.println("删除定时任务:" + id);
            Task task = taskMap.get(id);
            task.getScheduledFuture().cancel(true);
            taskMap.remove(id);
        }

        return "success";
    }

    /**
     * 更新定时任务
     *
     * @param id
     * @return
     */
    @RequestMapping("/updateTask/{id}")
    public String update(@PathVariable("id") String id, @RequestBody String cron) {
        System.out.println("更新定时任务: " + id);
        if (taskMap.containsKey(id)) {
            Task task = taskMap.get(id);
            task.getScheduledFuture().cancel(true);

            ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(task.getRunnable(), new Trigger() {
                @Override
                public Date nextExecutionTime(TriggerContext triggerContext) {
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }
            });

            task.setScheduledFuture(future);
            //taskMap.put(id, task);
        }

        return "update success";
    }
}

@Data
@Slf4j
class Task {
    private String taskId;
    private Runnable runnable;
    private ScheduledFuture scheduledFuture;
    private String cron;

    public Task(String taskId) {
        this.taskId = taskId;
        runnable = () -> {
            log.info("任务taskId: " + taskId);
        };
        cron = "0/5 * * * * ?";
    }
}